import React, { useRef, useEffect, useState, CSSProperties, JSX } from 'react'
import * as BABYLON from '@babylonjs/core'
import '@babylonjs/loaders/glTF'

export default function BabylonDemo(): JSX.Element {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const sceneRef = useRef<BABYLON.Scene | null>(null)
  const engineRef = useRef<BABYLON.Engine | null>(null)
  const meshRef = useRef<BABYLON.AbstractMesh | null>(null)
  const originalPositions = useRef<Float32Array | null>(null)
  const [isDeforming, setIsDeforming] = useState<boolean>(false)

  useEffect(() => {
    if (!canvasRef.current) return

    // 创建引擎和场景
    const engine = new BABYLON.Engine(canvasRef.current, true)
    engineRef.current = engine
    
    const scene = new BABYLON.Scene(engine)
    sceneRef.current = scene
    
    // 创建相机
    const camera = new BABYLON.ArcRotateCamera(
      'camera',
      -Math.PI / 2,
      Math.PI / 2.5,
      3,
      new BABYLON.Vector3(0, -0.3, 0),
      scene
    )
    camera.attachControl(canvasRef.current, true)
    camera.setTarget(new BABYLON.Vector3(0, -0.3, 0))
    camera.lowerRadiusLimit = 0.5
    camera.upperRadiusLimit = 5

    // 创建光源
    const ambientLight = new BABYLON.HemisphericLight('ambientLight', new BABYLON.Vector3(0, 1, 0), scene)
    ambientLight.intensity = 0.5

    const directionalLight = new BABYLON.DirectionalLight('directionalLight', new BABYLON.Vector3(-1, -1, -1), scene)
    directionalLight.position = new BABYLON.Vector3(3, 3, 3)
    directionalLight.intensity = 0.8
    
    // 启用阴影
    const shadowGenerator = new BABYLON.ShadowGenerator(1024, directionalLight)
    shadowGenerator.useBlurExponentialShadowMap = true

    // 创建地面
    const ground = BABYLON.MeshBuilder.CreateGround('ground', { width: 10, height: 10 }, scene)
    ground.position.y = -1.5
    ground.receiveShadows = true
    
    // 地面材质
    const groundMaterial = new BABYLON.StandardMaterial('groundMaterial', scene)
    groundMaterial.diffuseColor = new BABYLON.Color3(0.3, 0.3, 0.3)
    groundMaterial.specularColor = new BABYLON.Color3(0, 0, 0)
    ground.material = groundMaterial

    // 加载 GLB 模型
    BABYLON.SceneLoader.ImportMesh('', '/models/', 'shoe.glb', scene, (meshes: BABYLON.AbstractMesh[]) => {
      if (meshes.length > 0) {
        const rootMesh = meshes[0]
        rootMesh.position = new BABYLON.Vector3(0, -0.3, 0)
        
        // 找到第一个有几何体的网格
        let targetMesh: BABYLON.Mesh | null = null
        meshes.forEach(mesh => {
          if (mesh instanceof BABYLON.Mesh && mesh.geometry && mesh.getVerticesData) {
            targetMesh = mesh
          }
        })
        
        if (targetMesh) {
          meshRef.current = targetMesh
          
          // 保存原始顶点位置
          const positions = targetMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind)
          if (positions) {
            originalPositions.current = new Float32Array(positions)
          }
          
          // 启用阴影
          shadowGenerator.addShadowCaster(targetMesh)
          targetMesh.receiveShadows = true
        }
      }
    })

    // 变形功能
    let isMouseDown = false
    let selectedVertexIndex = -1

    const onPointerDown = (event: PointerEvent): void => {
      if (event.shiftKey && meshRef.current) {
        isMouseDown = true
        setIsDeforming(true)
        
        // 射线检测
        const pickInfo = scene.pick(scene.pointerX, scene.pointerY)
        if (pickInfo.hit && pickInfo.pickedMesh === meshRef.current) {
          const mesh = pickInfo.pickedMesh as BABYLON.Mesh
          const faceId = pickInfo.faceId
          
          if (faceId !== undefined && faceId >= 0) {
            // 获取面的顶点索引
            const indices = mesh.getIndices()
            if (indices) {
              const vertexIndex = indices[faceId * 3] // 取第一个顶点
              selectedVertexIndex = vertexIndex
            }
          }
        }
      }
    }

    const onPointerMove = (event: PointerEvent): void => {
      if (isMouseDown && selectedVertexIndex >= 0 && meshRef.current) {
        const mesh = meshRef.current as BABYLON.Mesh
        const positions = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind)
        
        if (positions) {
          const sensitivity = 0.01
          const movementX = event.movementX || 0
          const movementY = event.movementY || 0
          
          // 修改选中顶点位置
          const index = selectedVertexIndex * 3
          positions[index] += movementX * sensitivity     // X
          positions[index + 1] -= movementY * sensitivity // Y
          
          // 影响周围顶点
          const influenceRadius = 0.2
          const selectedPos = new BABYLON.Vector3(
            positions[index],
            positions[index + 1],
            positions[index + 2]
          )
          
          for (let i = 0; i < positions.length; i += 3) {
            if (i === index) continue
            
            const pos = new BABYLON.Vector3(positions[i], positions[i + 1], positions[i + 2])
            const distance = BABYLON.Vector3.Distance(selectedPos, pos)
            
            if (distance < influenceRadius) {
              const influence = 1 - (distance / influenceRadius)
              const factor = influence * 0.3
              
              positions[i] += movementX * sensitivity * factor
              positions[i + 1] -= movementY * sensitivity * factor
            }
          }
          
          // 更新顶点数据
          mesh.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions)
          mesh.createNormals(true) // 重新计算法线
        }
      }
    }

    const onPointerUp = (): void => {
      isMouseDown = false
      selectedVertexIndex = -1
      setIsDeforming(false)
    }

    // 重置功能
    const resetDeformation = (): void => {
      if (meshRef.current && originalPositions.current) {
        const mesh = meshRef.current as BABYLON.Mesh
        mesh.updateVerticesData(
          BABYLON.VertexBuffer.PositionKind, 
          originalPositions.current
        )
        mesh.createNormals(true)
      }
    }

    // 键盘事件
    const onKeyDown = (event: KeyboardEvent): void => {
      if (event.key === 'r' || event.key === 'R') {
        resetDeformation()
      }
    }

    // 绑定事件
    canvasRef.current.addEventListener('pointerdown', onPointerDown)
    canvasRef.current.addEventListener('pointermove', onPointerMove)
    canvasRef.current.addEventListener('pointerup', onPointerUp)
    window.addEventListener('keydown', onKeyDown)

    // 渲染循环
    engine.runRenderLoop(() => {
      scene.render()
    })

    // 窗口大小调整
    const handleResize = (): void => {
      engine.resize()
    }
    window.addEventListener('resize', handleResize)

    // 清理函数
    return () => {
      if (canvasRef.current) {
        canvasRef.current.removeEventListener('pointerdown', onPointerDown)
        canvasRef.current.removeEventListener('pointermove', onPointerMove)
        canvasRef.current.removeEventListener('pointerup', onPointerUp)
      }
      window.removeEventListener('keydown', onKeyDown)
      window.removeEventListener('resize', handleResize)
      
      if (engineRef.current) {
        engineRef.current.dispose()
      }
    }
  }, [])

  const containerStyle: CSSProperties = {
    width: '100vw', 
    height: 'calc(100vh - 60px)', 
    position: 'relative'
  }

  const instructionStyle: CSSProperties = {
    position: 'absolute',
    top: 20,
    left: 20,
    color: 'white',
    background: 'rgba(0,0,0,0.7)',
    padding: '10px',
    borderRadius: '5px',
    fontSize: '14px',
    zIndex: 1000
  }

  const titleStyle: CSSProperties = {
    marginBottom: '5px', 
    fontWeight: 'bold', 
    color: '#FF6B35'
  }

  const canvasStyle: CSSProperties = {
    width: '100%', 
    height: '100%', 
    display: 'block',
    outline: 'none'
  }

  return (
    <div style={containerStyle}>
      {/* 操作提示 */}
      <div style={instructionStyle}>
        <div style={titleStyle}>
          🚀 Babylon.js 演示
        </div>
        <div>🖱️ 普通拖拽：旋转视角</div>
        <div>⇧ + 拖拽：变形模型</div>
        <div>🔄 按 R 键：重置变形</div>
        <div>🖱️ 滚轮：缩放</div>
        {isDeforming && (
          <div style={{ color: '#FF6B35', marginTop: '5px' }}>
            🔧 变形模式激活
          </div>
        )}
      </div>
      
      <canvas 
        ref={canvasRef}
        style={canvasStyle}
      />
    </div>
  )
}